package com.kmxd.ams.app.system;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.kmxd.ams.client.system.ISysMenuSvc;
import com.kmxd.ams.client.system.dto.SysMenuAddDTO;
import com.kmxd.ams.client.system.dto.SysMenuEditDTO;
import com.kmxd.ams.client.system.dto.SysMenuQueryDTO;
import com.kmxd.ams.client.system.vo.RouteItemVO;
import com.kmxd.ams.client.system.vo.RouteMetaVO;
import com.kmxd.ams.client.system.vo.SysMenuListVO;
import com.kmxd.ams.client.system.vo.SysMenuVO;
import com.kmxd.ams.core.common.bo.LoginUser;
import com.kmxd.ams.core.common.bo.SysUserBO;
import com.kmxd.ams.core.common.constant.CacheConst;
import com.kmxd.ams.core.common.constant.ErrorCode;
import com.kmxd.ams.core.common.constant.MenuConst;
import com.kmxd.ams.core.common.enums.*;
import com.kmxd.ams.core.common.query.QueryGen;
import com.kmxd.ams.core.exception.BizTipException;
import com.kmxd.ams.core.util.SecurityUtil;
import com.kmxd.ams.infra.system.entity.SysMenu;
import com.kmxd.ams.infra.system.entity.SysRoleMenu;
import com.kmxd.ams.infra.system.entity.SysUserRole;
import com.kmxd.ams.infra.system.mapper.SysMenuMapper;
import com.kmxd.ams.infra.system.mapper.SysRoleMenuMapper;
import com.kmxd.ams.infra.system.mapper.SysUserRoleMapper;
import java.util.*;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
 * 菜单表 服务实现类
 *
 * @author admin
 * @since 2021-06-19
 */
@Service
@Slf4j
@AllArgsConstructor
@CacheConfig(cacheNames = CacheConst.CACHE_PREFIX_SYS_MENU)
public class SysMenuSvcImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements ISysMenuSvc {

  private SysMenuMapper sysMenuMapper;

  private SysUserRoleMapper sysUserRoleMapper;

  private SysRoleMenuMapper sysRoleMenuMapper;

  @Cacheable(keyGenerator = "myKeyGenerator")
  @Override
  public Page<SysMenuListVO> selectPage(Page reqPage, SysMenuQueryDTO req) {
    LambdaQueryWrapper<SysMenu> queryWrapper = Wrappers.lambdaQuery();
    queryWrapper.eq(Objects.nonNull(req.getParentId()), SysMenu::getParentId, req.getParentId());
    queryWrapper.like(
        StrUtil.isNotBlank(req.getMenuName()), SysMenu::getMenuName, req.getMenuName());
    queryWrapper.orderByAsc(SysMenu::getSort);
    Page<SysMenu> page = sysMenuMapper.selectPage(reqPage, queryWrapper);
    Page<SysMenuListVO> voPage = BeanUtil.copyProperties(page, Page.class);
    voPage.setRecords(BeanUtil.copyToList(page.getRecords(), SysMenuListVO.class));
    return voPage;
  }

  @Cacheable(keyGenerator = "myKeyGenerator")
  @Override
  public List<SysMenuListVO> selectList(SysMenuQueryDTO req) {
    LambdaQueryWrapper<SysMenu> queryWrapper =
        QueryGen.init(new QueryWrapper<SysMenu>(), req).lambda();
    List<SysMenu> menuList = sysMenuMapper.selectList(queryWrapper);
    return BeanUtil.copyToList(menuList, SysMenuListVO.class);
  }

  @Cacheable(keyGenerator = "myKeyGenerator")
  @Override
  public List<SysMenu> selectListAll() {
    LambdaQueryWrapper<SysMenu> queryWrapper = Wrappers.lambdaQuery();
    queryWrapper.orderBy(true, false, SysMenu::getSort, SysMenu::getMenuName);
    return sysMenuMapper.selectList(queryWrapper);
  }

  @Override
  public List<Long> selectMenuByRole(MenuGroupEnum groupEnum, List<SysMenu> menus) {
    // 特殊处理普通用户
    if (ObjectUtil.equals(groupEnum.getCode(), MenuGroupEnum.EMPTY.getCode())) {
      // 仪表盘，检索
      Set<Long> menuDatas =
          menus.stream()
              .filter(
                  item ->
                      MenuConst.DASHBOARD_ID.contains(item.getId())
                          || ObjectUtil.equals(MenuConst.SEARCH_ID, item.getId())
                          || MenuConst.SEARCH_IDS.contains(item.getId()))
              .map(SysMenu::getId)
              .collect(Collectors.toSet());
      List<Long> menuIds = getMenuIds(menuDatas, menus);
      menuDatas.addAll(menuIds);
      return menuDatas.stream().distinct().collect(Collectors.toList());
    }
    // 需要特殊处理，单位领导，档案部门领导，部门领导
    if (ObjectUtil.equals(groupEnum.getCode(), MenuGroupEnum.UNIT_LEADER.getCode())) {
      // 仪表盘，检索，宗外移交、接收
      Set<Long> menuDatas =
          menus.stream()
              .filter(
                  item ->
                      MenuConst.DASHBOARD_ID.contains(item.getId())
                          || ObjectUtil.equals(MenuConst.SEARCH_ID, item.getId())
                          || MenuConst.SEARCH_IDS.contains(item.getId())
                          || ObjectUtil.equals(MenuConst.RECEIVE_ID, item.getId())
                          || ObjectUtil.equals(MenuConst.RECEIVE_LIST_ID, item.getId())
                          || ObjectUtil.equals(MenuConst.RECEIVE_LIST_ID, item.getParentId())
                          || ObjectUtil.equals(
                              MenuConst.TRANSFER_FONDS_RECEIVE_ID, item.getParentId())
                          || ObjectUtil.equals(MenuConst.TRANSFER_FONDS_RECEIVE_ID, item.getId())
                          || ObjectUtil.equals(MenuConst.TRANSFER_RECEIVE_ID, item.getId())
                          || ObjectUtil.equals(MenuConst.FONDS_RECEIVE_ID, item.getId())
                          || ObjectUtil.equals(MenuConst.FONDS_RECEIVE_ID, item.getParentId()))
              .map(SysMenu::getId)
              .collect(Collectors.toSet());
      List<Long> menuIds = getMenuIds(menuDatas, menus);
      menuDatas.addAll(menuIds);
      return menuDatas.stream().distinct().collect(Collectors.toList());
    }

    // 档案部门领导
    if (ObjectUtil.equals(groupEnum.getCode(), MenuGroupEnum.ARCH_DEPT_LEADER.getCode())) {
      Set<Long> menuDatas =
          menus.stream()
              .filter(
                  item ->
                      StrUtil.split(item.getMenuGroup(), ",")
                              .contains(MenuGroupEnum.DEPT_LEADER.getCode())
                          || MenuConst.DASHBOARD_ID.contains(item.getId())
                          || ObjectUtil.equals(MenuConst.SEARCH_ID, item.getId())
                          || MenuConst.SEARCH_IDS.contains(item.getId())
                          || ObjectUtil.equals(MenuConst.RECEIVE_ID, item.getId())
                          || ObjectUtil.equals(MenuConst.RECEIVE_LIST_ID, item.getId())
                          || ObjectUtil.equals(MenuConst.RECEIVE_LIST_ID, item.getParentId())
                          || ObjectUtil.equals(
                              MenuConst.TRANSFER_FONDS_RECEIVE_ID, item.getParentId())
                          || ObjectUtil.equals(MenuConst.TRANSFER_FONDS_RECEIVE_ID, item.getId())
                          || ObjectUtil.equals(MenuConst.TRANSFER_RECEIVE_ID, item.getId())
                          || ObjectUtil.equals(MenuConst.FONDS_RECEIVE_ID, item.getId())
                          || ObjectUtil.equals(MenuConst.FONDS_RECEIVE_ID, item.getParentId()))
              .map(SysMenu::getId)
              .collect(Collectors.toSet());
      List<Long> menuIds = getMenuIds(menuDatas, menus);
      menuDatas.addAll(menuIds);
      return menuDatas.stream().distinct().collect(Collectors.toList());
    }

    // 部门领导
    if (ObjectUtil.equals(groupEnum.getCode(), MenuGroupEnum.DEPT_LEADER.getCode())) {
      // 仪表盘，检索，宗内移交
      Set<Long> menuDatas =
          menus.stream()
              .filter(
                  item ->
                      MenuConst.DASHBOARD_ID.contains(item.getId())
                          || ObjectUtil.equals(MenuConst.SEARCH_ID, item.getId())
                          || MenuConst.SEARCH_IDS.contains(item.getId())
                          || ObjectUtil.equals(MenuConst.RECEIVE_ID, item.getId())
                          || ObjectUtil.equals(MenuConst.RECEIVE_LIST_ID, item.getId())
                          || ObjectUtil.equals(MenuConst.RECEIVE_LIST_ID, item.getParentId())
                          || ObjectUtil.equals(
                              MenuConst.TRANSFER_FONDS_RECEIVE_ID, item.getParentId())
                          || ObjectUtil.equals(MenuConst.TRANSFER_FONDS_RECEIVE_ID, item.getId())
                          || ObjectUtil.equals(MenuConst.TRANSFER_RECEIVE_ID, item.getId())
                          || ObjectUtil.equals(MenuConst.FONDS_RECEIVE_ID, item.getId())
                          || ObjectUtil.equals(MenuConst.FONDS_RECEIVE_ID, item.getParentId()))
              .map(SysMenu::getId)
              .collect(Collectors.toSet());
      List<Long> menuIds = getMenuIds(menuDatas, menus);
      menuDatas.addAll(menuIds);
      return menuDatas.stream().distinct().collect(Collectors.toList());
    }

    Set<Long> menuDatas =
        menus.stream()
            .filter(
                item ->
                    StrUtil.split(item.getMenuGroup(), ",").contains(groupEnum.getCode())
                        || MenuConst.DASHBOARD_ID.contains(item.getId()))
            .map(SysMenu::getId)
            .collect(Collectors.toSet());
    List<Long> menuIds = getMenuIds(menuDatas, menus);
    menuDatas.addAll(menuIds);
    return menuDatas.stream().distinct().collect(Collectors.toList());
  }

  private List<Long> getMenuIds(Set<Long> currentIds, List<SysMenu> allList) {
    return allList.stream()
        .filter(
            item ->
                currentIds.contains(item.getParentId())
                        && ObjectUtil.equals(item.getMenuType(), MenuTypeEnum.BUTTON.getCode())
                    || currentIds.contains(item.getId()))
        .map(SysMenu::getId)
        .collect(Collectors.toList());
  }

  @CacheEvict(allEntries = true)
  @Override
  @Transactional(rollbackFor = Exception.class)
  public void add(SysMenuAddDTO req) {
    // 当前节点为目录
    if (Objects.nonNull(req.getParentId())
        && Objects.equals(req.getMenuType(), MenuTypeEnum.DIR.getCode())) {
      SysMenu sysMenuParent = sysMenuMapper.selectById(req.getParentId());
      if (Objects.equals(sysMenuParent.getMenuType(), MenuTypeEnum.MENU.getCode())) {
        throw BizTipException.instance(ErrorCode.VALIDATE_ERROR, "上级节点不允许为菜单");
      }
      if (Objects.equals(sysMenuParent.getMenuType(), MenuTypeEnum.BUTTON.getCode())) {
        throw BizTipException.instance(ErrorCode.VALIDATE_ERROR, "上级节点不允许为按钮");
      }
    }
    // 当前节点为菜单
    if (Objects.nonNull(req.getParentId())
        && Objects.equals(req.getMenuType(), MenuTypeEnum.MENU.getCode())) {
      SysMenu sysMenuParent = sysMenuMapper.selectById(req.getParentId());
      if (Objects.equals(sysMenuParent.getMenuType(), MenuTypeEnum.MENU.getCode())) {
        throw BizTipException.instance(ErrorCode.VALIDATE_ERROR, "上级节点不允许为菜单");
      }
      if (Objects.equals(sysMenuParent.getMenuType(), MenuTypeEnum.BUTTON.getCode())) {
        throw BizTipException.instance(ErrorCode.VALIDATE_ERROR, "上级节点不允许为按钮");
      }
    }
    SysMenu entity = BeanUtil.copyProperties(req, SysMenu.class);
    if (Objects.isNull(req.getParentId())) {
      entity.setParentId(0L);
    }
    sysMenuMapper.insert(entity);
  }

  @CacheEvict(allEntries = true)
  @Override
  @Transactional(rollbackFor = Exception.class)
  public void edit(SysMenuEditDTO req) {
    // 当前节点为目录
    if (Objects.nonNull(req.getParentId())
        && Objects.equals(req.getMenuType(), MenuTypeEnum.DIR.getCode())) {
      SysMenu sysMenuParent = sysMenuMapper.selectById(req.getParentId());
      if (Objects.equals(sysMenuParent.getMenuType(), MenuTypeEnum.MENU.getCode())) {
        throw BizTipException.instance(ErrorCode.VALIDATE_ERROR, "上级节点不允许为菜单");
      }
      if (Objects.equals(sysMenuParent.getMenuType(), MenuTypeEnum.BUTTON.getCode())) {
        throw BizTipException.instance(ErrorCode.VALIDATE_ERROR, "上级节点不允许为按钮");
      }
    }
    // 当前节点为菜单
    if (Objects.nonNull(req.getParentId())
        && Objects.equals(req.getMenuType(), MenuTypeEnum.MENU.getCode())) {
      SysMenu sysMenuParent = sysMenuMapper.selectById(req.getParentId());
      if (Objects.equals(sysMenuParent.getMenuType(), MenuTypeEnum.MENU.getCode())) {
        throw BizTipException.instance(ErrorCode.VALIDATE_ERROR, "上级节点不允许为菜单");
      }
      if (Objects.equals(sysMenuParent.getMenuType(), MenuTypeEnum.BUTTON.getCode())) {
        throw BizTipException.instance(ErrorCode.VALIDATE_ERROR, "上级节点不允许为按钮");
      }
    }
    SysMenu entity = BeanUtil.copyProperties(req, SysMenu.class);
    if (Objects.isNull(req.getParentId())) {
      entity.setParentId(0L);
    }
    if (entity.getMenuType().equals(MenuTypeEnum.DIR.getCode())) {
      entity.setComponent("");
      entity.setPermission("");
      entity.setKeepalive("");
      entity.setFrame(null);
      entity.setLinkUrl("");
    }
    if (entity.getMenuType().equals(MenuTypeEnum.MENU.getCode())) {
      entity.setPermission("");
      if (entity.getLinkExternal().equals(LinkExternalEnum.NO.getCode())) {
        entity.setFrame(null);
        entity.setLinkUrl("");
      }
    }
    if (entity.getMenuType().equals(MenuTypeEnum.BUTTON.getCode())) {
      entity.setIcon("");
      entity.setRoutePath("");
      entity.setComponent("");
      entity.setVisible("");
      entity.setKeepalive("");
      entity.setFrame(null);
      entity.setLinkUrl("");
    }
    sysMenuMapper.updateById(entity);
  }

  @CacheEvict(allEntries = true)
  @Override
  @Transactional(rollbackFor = Exception.class)
  public void remove(String ids) {
    List<String> idList = Arrays.asList(ids.split(","));
    idList.forEach(
        item -> {
          SysMenu sysMenu = sysMenuMapper.selectById(item);
          Long childrenCount =
              sysMenuMapper.selectCount(
                  Wrappers.lambdaQuery(SysMenu.class).eq(SysMenu::getParentId, item));
          if (null != childrenCount && childrenCount > 0) {
            throw BizTipException.instance(
                ErrorCode.VALIDATE_ERROR,
                String.format("菜单【%s】存在下级菜单，无法删除", sysMenu.getMenuName()));
          }
        });
    idList.forEach(
        item -> {
          sysMenuMapper.deleteById(item);
        });
  }

  @Cacheable(keyGenerator = "myKeyGenerator")
  @Override
  public SysMenuVO view(Long id) {
    SysMenu entity = sysMenuMapper.selectById(id);
    return BeanUtil.copyProperties(entity, SysMenuVO.class);
  }

  @Override
  public List<Tree<String>> listMenuTree() {
    ISysMenuSvc sysMenuSvc = SpringUtil.getBean(ISysMenuSvc.class);
    List<SysMenu> sysMenuList = sysMenuSvc.selectListAll();
    List treeNodeList =
        sysMenuList.stream()
            .filter(menu -> !menu.getMenuType().equals(MenuTypeEnum.BUTTON.getCode()))
            .map(
                item -> {
                  TreeNode treeNode = new TreeNode();
                  treeNode.setId(item.getId().toString());
                  treeNode.setName(item.getMenuName());
                  treeNode.setParentId(item.getParentId().toString());
                  treeNode.setWeight(item.getSort());
                  Map extra = Maps.newHashMap();
                  extra.put("icon", item.getIcon());
                  treeNode.setExtra(extra);
                  return treeNode;
                })
            .collect(Collectors.toList());
    List<Tree<String>> treeList = TreeUtil.build(treeNodeList, "0");
    return CollectionUtils.isEmpty(treeList) ? new ArrayList() : treeList;
  }

  @Override
  public List<Tree<String>> selectMenuTreeAndExcludeNode(String nodeId) {
    List<SysMenu> sysMenuList =
        sysMenuMapper.selectList(
            Wrappers.lambdaQuery(SysMenu.class)
                .ne(StrUtil.isNotBlank(nodeId), SysMenu::getId, nodeId));
    List treeNodeList =
        sysMenuList.stream()
            .map(
                item -> {
                  TreeNode treeNode = new TreeNode();
                  treeNode.setId(item.getId().toString());
                  treeNode.setName(item.getMenuName());
                  treeNode.setParentId(item.getParentId().toString());
                  treeNode.setWeight(item.getSort());
                  Map extra = Maps.newHashMap();
                  extra.put("icon", item.getIcon());
                  treeNode.setExtra(extra);
                  return treeNode;
                })
            .collect(Collectors.toList());
    List<Tree<String>> treeList = TreeUtil.build(treeNodeList, "0");
    return CollectionUtils.isEmpty(treeList) ? new ArrayList() : treeList;
  }

  @Override
  public List<Tree<String>> selectMenuTree() {
    ISysMenuSvc sysMenuSvc = SpringUtil.getBean(ISysMenuSvc.class);
    List<SysMenu> sysMenuList = sysMenuSvc.selectListAll();
    List treeNodeList =
        sysMenuList.stream()
            .map(
                item -> {
                  TreeNode treeNode = new TreeNode();
                  treeNode.setId(item.getId().toString());
                  treeNode.setName(item.getMenuName());
                  treeNode.setParentId(item.getParentId().toString());
                  treeNode.setWeight(item.getSort());
                  Map extra = Maps.newHashMap();
                  extra.put("icon", item.getIcon());
                  treeNode.setExtra(extra);
                  return treeNode;
                })
            .collect(Collectors.toList());
    List<Tree<String>> treeList = TreeUtil.build(treeNodeList, "0");
    return CollectionUtils.isEmpty(treeList) ? new ArrayList() : treeList;
  }

  @Override
  public Set<String> getPermissionsByUserId(Long userId) {
    // 查询角色列表
    List<SysUserRole> sysUserRoleList =
        sysUserRoleMapper.selectList(
            Wrappers.lambdaQuery(SysUserRole.class).eq(SysUserRole::getUserId, userId));
    if (sysUserRoleList.isEmpty()) {
      return Sets.newHashSet();
    }
    List<Long> roleIdList =
        sysUserRoleList.stream().map(item -> item.getRoleId()).collect(Collectors.toList());
    // 查询按钮菜单权限标识
    List<SysRoleMenu> sysRoleMenuList =
        sysRoleMenuMapper.selectList(
            Wrappers.lambdaQuery(SysRoleMenu.class).in(SysRoleMenu::getRoleId, roleIdList));
    if (sysRoleMenuList.isEmpty()) {
      return Sets.newHashSet();
    }
    // 查询菜单
    Set<Long> menuIds =
        sysRoleMenuList.stream().map(item -> item.getMenuId()).collect(Collectors.toSet());
    LambdaQueryWrapper<SysMenu> queryWrapper = Wrappers.lambdaQuery();
    queryWrapper.eq(SysMenu::getMenuType, MenuTypeEnum.BUTTON.getCode());
    queryWrapper.in(SysMenu::getId, menuIds);
    List<SysMenu> sysMenuList = sysMenuMapper.selectList(queryWrapper);
    return sysMenuList.stream().map(item -> item.getPermission()).collect(Collectors.toSet());
  }

  @Override
  public Set<String> getPermissionsByRoleId(Long roleId) {
    List<Long> roleIdList = Lists.newArrayList();
    roleIdList.add(roleId);
    // 查询按钮菜单权限标识
    List<SysRoleMenu> sysRoleMenuList =
        sysRoleMenuMapper.selectList(
            Wrappers.lambdaQuery(SysRoleMenu.class).in(SysRoleMenu::getRoleId, roleIdList));
    if (sysRoleMenuList.isEmpty()) {
      return Sets.newHashSet();
    }
    // 查询菜单
    Set<Long> menuIds =
        sysRoleMenuList.stream().map(item -> item.getMenuId()).collect(Collectors.toSet());
    LambdaQueryWrapper<SysMenu> queryWrapper = Wrappers.lambdaQuery();
    queryWrapper.eq(SysMenu::getMenuType, MenuTypeEnum.BUTTON.getCode());
    queryWrapper.in(SysMenu::getId, menuIds);
    List<SysMenu> sysMenuList = sysMenuMapper.selectList(queryWrapper);
    return sysMenuList.stream().map(item -> item.getPermission()).collect(Collectors.toSet());
  }

  @Cacheable(keyGenerator = "myKeyGenerator")
  @Override
  public List<SysMenu> listGrantMenuByUserId(Long userId) {
    // 查询角色列表
    List<SysUserRole> sysUserRoleList =
        sysUserRoleMapper.selectList(
            Wrappers.lambdaQuery(SysUserRole.class).eq(SysUserRole::getUserId, userId));
    if (sysUserRoleList.isEmpty()) {
      return new ArrayList();
    }
    List<Long> roleIdList =
        sysUserRoleList.stream().map(item -> item.getRoleId()).collect(Collectors.toList());
    // 查询角色菜单
    List<SysRoleMenu> sysRoleMenuList =
        sysRoleMenuMapper.selectList(
            Wrappers.lambdaQuery(SysRoleMenu.class).in(SysRoleMenu::getRoleId, roleIdList));
    if (sysRoleMenuList.isEmpty()) {
      return new ArrayList();
    }
    // 查询菜单
    Set<Long> menuIds =
        sysRoleMenuList.stream().map(item -> item.getMenuId()).collect(Collectors.toSet());
    LambdaQueryWrapper<SysMenu> queryWrapper = Wrappers.lambdaQuery();
    queryWrapper.in(SysMenu::getMenuType, MenuTypeEnum.DIR.getCode(), MenuTypeEnum.MENU.getCode());
    queryWrapper.in(SysMenu::getId, menuIds);
    return sysMenuMapper.selectList(queryWrapper);
  }

  @Cacheable(keyGenerator = "myKeyGenerator")
  @Override
  public List<SysMenu> listGrantMenuByRoleId(Long roleId) {
    List<Long> roleIdList = Lists.newArrayList();
    roleIdList.add(roleId);
    // 查询角色菜单
    List<SysRoleMenu> sysRoleMenuList =
        sysRoleMenuMapper.selectList(
            Wrappers.lambdaQuery(SysRoleMenu.class).in(SysRoleMenu::getRoleId, roleIdList));
    if (sysRoleMenuList.isEmpty()) {
      return new ArrayList();
    }
    // 查询菜单
    Set<Long> menuIds =
        sysRoleMenuList.stream().map(item -> item.getMenuId()).collect(Collectors.toSet());
    LambdaQueryWrapper<SysMenu> queryWrapper = Wrappers.lambdaQuery();
    queryWrapper.in(SysMenu::getMenuType, MenuTypeEnum.DIR.getCode(), MenuTypeEnum.MENU.getCode());
    queryWrapper.in(SysMenu::getId, menuIds);
    return sysMenuMapper.selectList(queryWrapper);
  }

  //  @Cacheable(keyGenerator = "myKeyGenerator")
  @Override
  public List<RouteItemVO> getMenuList() {

    ISysMenuSvc sysMenuSvc = SpringUtil.getBean(ISysMenuSvc.class);
    List<SysMenu> sysMenuList;
    LoginUser loginUser = SecurityUtil.getLoginUser();
    SysUserBO sysUserBO = loginUser.getSysUser();
    if (SecurityUtil.isRootGroup()) {
      sysMenuList =
          sysMenuSvc.selectListAll().stream()
              .filter(
                  x ->
                      (x.getMenuType().equals(MenuTypeEnum.DIR.getCode())
                          || x.getMenuType().equals(MenuTypeEnum.MENU.getCode())))
              .collect(Collectors.toList());
    } else {
      if (sysUserBO.getRoles().size() == 1) {
        sysMenuList = this.listGrantMenuByRoleId(loginUser.getRoleId());
      } else {
        sysMenuList = this.listGrantMenuByUserId(sysUserBO.getId());
      }
    }
    List<RouteItemVO> routeItemVOList =
        sysMenuList.stream()
            .filter(item -> item.getParentId().intValue() == 0)
            .sorted(Comparator.comparing(SysMenu::getSort))
            .map(
                item -> {
                  RouteItemVO node = convertToRoute(item);
                  node.setChildren(getChildrenList(item, sysMenuList));
                  node.setMenuType(item.getMenuType());
                  return node;
                })
            .collect(Collectors.toList());
    return routeItemVOList;
  }

  private List<RouteItemVO> getChildrenList(SysMenu root, List<SysMenu> list) {
    List<RouteItemVO> childrenList =
        list.stream()
            .filter(item -> item.getParentId().equals(root.getId()))
            .sorted(Comparator.comparing(SysMenu::getSort))
            .map(
                item -> {
                  RouteItemVO node = convertToRoute(item);
                  node.setChildren(getChildrenList(item, list));
                  node.setMenuType(item.getMenuType());
                  return node;
                })
            .collect(Collectors.toList());
    return childrenList;
  }

  private RouteItemVO convertToRoute(SysMenu item) {
    RouteItemVO node = new RouteItemVO();
    node.setName(StrUtil.upperFirst(item.getRoutePath()));
    node.setPath(item.getRoutePath());
    node.setComponent(item.getComponent());
    // 一级目录
    if (Objects.equals(item.getMenuType(), MenuTypeEnum.DIR.getCode())
        && item.getParentId().intValue() == 0) {
      node.setPath("/" + item.getRoutePath());
      node.setComponent(MenuConst.LAYOUT);
    }
    // 外部链接
    if (Objects.equals(item.getMenuType(), MenuTypeEnum.MENU.getCode())
        && Objects.equals(item.getLinkExternal(), LinkExternalEnum.YES.getCode())) {
      node.setComponent(MenuConst.IFRAME);
    }
    RouteMetaVO routeMetaVO = new RouteMetaVO();
    routeMetaVO.setTitle(item.getMenuName());
    routeMetaVO.setIcon(item.getIcon());
    routeMetaVO.setHideMenu(
        StrUtil.isNotBlank(item.getVisible())
            && item.getVisible().equals(VisibleEnum.HIDE.getCode()));
    // 菜单
    if (Objects.equals(item.getMenuType(), MenuTypeEnum.MENU.getCode())) {
      routeMetaVO.setIgnoreKeepAlive(
          ObjectUtil.isNotEmpty(item.getKeepalive())
              && item.getKeepalive().equals(KeepaliveEnum.YES.getCode()));
    }
    // 外部链接
    if (Objects.equals(item.getMenuType(), MenuTypeEnum.MENU.getCode())
        && Objects.equals(item.getLinkExternal(), LinkExternalEnum.YES.getCode())) {
      // 内嵌
      if (Objects.equals(item.getFrame(), FrameEnum.YES.getCode())) {
        routeMetaVO.setFrameSrc(item.getLinkUrl());
      }
      // 外嵌
      if (item.getFrame().equals(FrameEnum.NO.getCode())) {
        node.setPath(item.getLinkUrl());
      }
    }
    node.setMeta(routeMetaVO);
    return node;
  }

  @CacheEvict(allEntries = true)
  @Override
  public void clearAllCache() {
    log.info("清除系统缓存");
  }
}
